#include "GameConfigManager.h"
#include "pugixml.hpp"
#include <map>
using namespace std;

SINGLETON_CLASS_INIT(CGameConfigManager);

static void _loadServerConfig(ServerConfig &cfg, pugi::xml_node &node)
{
	cfg.id = node.attribute("Id").as_int();
	cfg.ip = node.attribute("Ip").as_string();
	cfg.port = node.attribute("Port").as_int();
	cfg.gameId = node.attribute("GameId").as_int();

	cfg.ioServiceCount = node.attribute("IoCount").empty() ? 1 : node.attribute("IoCount").as_int();
	cfg.useWorkerEvent = node.attribute("UseEventWorker").empty() ? true : (node.attribute("UseEventWorker").as_int() == 1);
	cfg.eventWorkerCount = node.attribute("WorkerCount").empty() ? 1 : node.attribute("WorkerCount").as_int();
	cfg.eventQueueSize = node.attribute("EventQueueSize").as_int();

	cfg.szSend = node.attribute("SendSize").as_int();
	cfg.szRecv = node.attribute("RecvSize").as_int();
	cfg.connCount = node.attribute("ConnCount").as_int();

	cfg.rpcSzSend = node.attribute("RpcSendSize").as_int();
	cfg.rpcSzRecv = node.attribute("RpcRecvSize").as_int();
	cfg.rpcConnCount = node.attribute("RpcConnCount").as_int();

	cfg.heartBeatTime = node.attribute("HeartBeatTime").as_int();
}

static s32 _findLogLevel(const string &strlevel)
{
	static map<string, s32> _levelmap;
	if( _levelmap.size() == 0 )
	{
		_levelmap[ "DEBUG" ] = SGLib::CLogExManager::E_LogLevel_Debug;
		_levelmap[ "INFO" ] = SGLib::CLogExManager::E_LogLevel_Info;
		_levelmap[ "WARN" ] = SGLib::CLogExManager::E_LogLevel_Warn;
		_levelmap[ "ERROR" ] = SGLib::CLogExManager::E_LogLevel_Error;
	}
	map<string, s32>::iterator it = _levelmap.find( strlevel );
	if( it != _levelmap.end() )
	{
		return it->second;
	}
	return SGLib::CLogExManager::E_LogLevel_Max;
}

static s32 _findLogRollingMode(const string &strMode)
{
	static map<string, s32> _modemap;
	if( _modemap.size() == 0 )
	{
		_modemap[ "DAY" ] = SGLib::CLogExManager::E_LogMode_Day;
		_modemap[ "HOUR" ] = SGLib::CLogExManager::E_LogMode_Hour;
	}
	map<string, s32>::iterator it = _modemap.find( strMode );
	if( it != _modemap.end() )
	{
		return it->second;
	}
	return SGLib::CLogExManager::E_LogMode_Hour;
}

static void _loadLogConfig(LogConfig &cfg, pugi::xml_node &node)
{
	cfg.file = node.attribute("File").as_string();

	string strMinLevel = node.attribute("MinLevel").as_string();
	string strMaxLevel = node.attribute("MaxLevel").as_string();
	string strRollingMode = node.attribute("RollingMode").as_string();
	
	s32 level = _findLogLevel( strMinLevel );
	cfg.minLevel = (level==SGLib::CLogExManager::E_LogLevel_Max) ? SGLib::CLogExManager::E_LogLevel_Debug : level;

	level = _findLogLevel( strMaxLevel );
	cfg.maxLevel = (level==SGLib::CLogExManager::E_LogLevel_Max) ? SGLib::CLogExManager::E_LogLevel_Error: level;

	cfg.rollingMode = _findLogRollingMode( strRollingMode );
}

static void _loadConnectsItems(vector<ConnectItem> &connItems, pugi::xml_node &node)
{
	for( pugi::xml_node conn = node.first_child(); conn; conn = conn.next_sibling() )
	{
		ConnectItem connItem;
		connItem.serverid = conn.attribute("ServerId").as_int();
		connItem.ip = conn.attribute("Ip").as_string();
		connItem.port = conn.attribute("Port").as_int();
		connItem.name = conn.attribute("Name").as_string();
		if( connItem.Valid() )
		{
			connItems.push_back( connItem );
		}

		if( connItem.name == "dbserver" )
		{
			CGameConfigManager::s_dbserverId = connItem.serverid;
		}
	}
}

s32 CGameConfigManager::s_dbserverId = 100;

void CGameConfigManager::Load(const string &cfgfile)
{
	pugi::xml_document doc;
	pugi::xml_parse_result result = doc.load_file( cfgfile.c_str() );
    if( result != pugi::status_ok )
    {
        printf( "CGameConfigManager::Load [%s] Error, result[%d]\n", 
            cfgfile.c_str(), (int)result );
        return;
    }
	pugi::xml_node cfg = doc.child( "GameConfig" );
	if( cfg.empty() )
	{
        printf( "CGameConfigManager::Load [%s] Error, not found child:GameConfig\n", cfgfile.c_str() );
		return;
	}
	
	pugi::xml_node server = cfg.child( "Server" );
	if( server.empty() )
	{
        printf( "CGameConfigManager::Load [%s] Error, not found child:Server\n", cfgfile.c_str() );
		return;
	}
	_loadServerConfig( m_serverCfg, server );

	pugi::xml_node logcfg = cfg.child( "Log" );
	if( logcfg.empty() )
	{
        printf( "CGameConfigManager::Load [%s] Error, not found child:Log\n", cfgfile.c_str() );
		return;
	}
	_loadLogConfig( m_logCfg, logcfg );


	pugi::xml_node conns = cfg.child( "Connects" );
	if( conns.empty() )
	{
        printf( "CGameConfigManager::Load [%s] Error, not found child:Connects\n", cfgfile.c_str() );
		return;
	}
	_loadConnectsItems( m_connItems, conns );
}
	
void CGameConfigManager::ReloadLogConfig(const std::string &cfgfile)
{
	pugi::xml_document doc;
	pugi::xml_parse_result result = doc.load_file( cfgfile.c_str() );
    if( result != pugi::status_ok )
    {
        printf( "CGameConfigManager::ReloadLogConfig [%s] Error, result[%d]\n", 
            cfgfile.c_str(), (int)result );
        return;
    }
	pugi::xml_node cfg = doc.child( "GameConfig" );
	if( cfg.empty() )
	{
        printf( "CGameConfigManager::ReloadLogConfig [%s] Error, not found child:GameConfig\n", cfgfile.c_str() );
		return;
	}
	
	pugi::xml_node logcfg = cfg.child( "Log" );
	if( logcfg.empty() )
	{
        printf( "CGameConfigManager::ReloadLogConfig [%s] Error, not found child:Log\n", cfgfile.c_str() );
		return;
	}
	_loadLogConfig( m_logCfg, logcfg );
}

const ServerConfig& CGameConfigManager::GetServerConfig()
{
	return m_serverCfg;
}

const LogConfig& CGameConfigManager::GetLogConfig()
{
	return m_logCfg;
}

s32 CGameConfigManager::GetConnectCount()
{
    return (s32)m_connItems.size();
}

const ConnectItem* CGameConfigManager::GetConnectItem(s32 idx)
{
    if( idx >= GetConnectCount() )
    {
        return NULL;
    }

    return &m_connItems[idx];
}

s32 CGameConfigManager::GetServerId(const char *ip, s32 port)
{
    vector<ConnectItem>::iterator it = m_connItems.begin();
    for( ; it != m_connItems.end(); ++it )
    {
        if( it->ip == ip && it->port == port )
        {
            return it->serverid;
        }
    }
    return 0;
}

bool CGameConfigManager::_FindConnectItem(s32 serverid)
{
    vector<ConnectItem>::iterator it = m_connItems.begin();
    for( ; it != m_connItems.end(); ++it )
    {
        if( it->serverid == serverid )
        {
            return true;
        }
    }
    return false;
}

